#pragma once

#include "../comm/comm.hpp"
#include "../comm/log.hpp"
// 负责编译临时文件

using namespace Ns_Comm;

class Compiler
{

public:
    Compiler() {}

    // 返回true 代表编译成功
    // 返回false 代表编译错误
    //                          传进来的是一个代码文件
    static bool CompileForCpp(const std::string &filename)
    {
        int id = fork();
        if (id < 0)
        {
            LOG(LogFatal, "%s中第 %d 行创建子进程错误\n", __FILE__, __LINE__);
            exit(Fork_Err);
        }
        else if (id == 0)
        {
            // 创建错误文件（编译错误时，将错误内容输入到这个文件中）
            umask(0);
            int compliererrfd = FileTool::Open(PathTool::SplicingCompilerErr(filename), O_CREAT | O_TRUNC | O_RDWR, 0644);
            if (compliererrfd < 0)
            {
                LOG(LogError, "%s中第 %d 行打开文件 %s 错误\n", __FILE__, __LINE__, CSTR(PathTool::SplicingCompilerErr(filename)));
                exit(OpenFile_Err);
            }
            // 将标准错误文件重定向到错误文件
            FileTool::Redirect(2, compliererrfd);

            // 子进程
            execlp("g++", "g++", "-o", PathTool::SplicingExe(filename).c_str(),
                   PathTool::SplicingCpp(filename).c_str(), "-DCOMPILE_ONLINE" ,"-std=c++11", nullptr);

            exit(0);
        }
        else
        {
            int wid = waitpid(id, nullptr, 0);
            if (wid < 0)
            {
                LOG(LogError, "%s中第 %d 行等待子进程失败\n", __FILE__, __LINE__);
                exit(WaitChild_Err);
            }
            if (FileTool::IsExist(PathTool::SplicingExe(filename)))
            {
                // 编译成功
                LOG(LogInfo, "编译成功\n");
                return true;
            }
            else
            {
                LOG(LogInfo, "编译失败\n");
                return false;
            }
        }
    }

    ~Compiler() {}
};